dependent_var <- "MEDHVAL"
predictors <- c("PCTBACHMOR", "NBELPOV100", "PCTVACANT", "PCTSINGLES")
summary_stats <- data %>%
select(all_of(c(dependent_var, predictors))) %>%
summarise_all(list(Mean = mean, SD = sd), na.rm = TRUE) %>%
pivot_longer(cols = everything(), names_to = "Variable", values_to = "Value") %>%
separate(Variable, into = c("Variable", "Stat"), sep = "_") %>%
pivot_wider(names_from = Stat, values_from = Value)
summary_stats$Variable <- recode(summary_stats$Variable,
"MEDHVAL" = "Median House Value",
"NBELPOV100" = "# Households Living in Poverty",
"PCTBACHMOR" = "% of Individuals with Bachelor’s Degrees or Higher",
"PCTVACANT" = "% of Vacant Houses",
"PCTSINGLES" = "% of Single House Units"
)
summary_stats <- summary_stats %>%
mutate(
Mean = round(Mean, 2),
SD = round(SD, 2)
)
summary_stats <- summary_stats %>%
arrange(Variable == "Median House Value")
predictor_rows <- which(summary_stats$Variable != "Median House Value")
dependent_rows <- which(summary_stats$Variable == "Median House Value")
# Determine the start and end rows for each group
start_pred <- min(predictor_rows)
end_pred <- max(predictor_rows)
start_dep <- min(dependent_rows)
end_dep <- max(dependent_rows)
# Create the table using kable and add extra formatting
kable(summary_stats, caption = "Summary Statistics",
align = c("l", "l", "l"), booktabs = TRUE, escape = FALSE ) %>%
add_header_above(c(" " = 1, "Statistics" = 2)) %>%
kable_styling(full_width = FALSE) %>%
group_rows("Predictors", start_pred, end_pred) %>%
group_rows("Dependent Variable", start_dep, end_dep)%>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = TRUE)
Summary Statistics
|
|
Statistics
|
|
Variable
|
Mean
|
SD
|
|
Predictors
|
|
% of Individuals with Bachelor’s Degrees or Higher
|
16.08
|
17.77
|
|
# Households Living in Poverty
|
189.77
|
164.32
|
|
% of Vacant Houses
|
11.29
|
9.63
|
|
% of Single House Units
|
9.23
|
13.25
|
|
Dependent Variable
|
|
Median House Value
|
66287.73
|
60006.08
|
#check 0
columns_to_check <- c(dependent_var, predictors)
zero_counts <- sapply(data[columns_to_check], function(x) sum(x == 0, na.rm = TRUE))
zero_counts[zero_counts > 0]
## PCTBACHMOR NBELPOV100 PCTVACANT PCTSINGLES
## 143 33 163 306
data <- data %>%
mutate(
LNMEDHVAL = log(MEDHVAL),
LNPCTBACHMOR = log(1+PCTBACHMOR),
LNNBELPOV100 = log(1+NBELPOV100),
LNPCTVACANT = log(1+PCTVACANT),
LNPCTSINGLES = log(1+PCTSINGLES)
)
longer_version<- data %>%
pivot_longer(cols = c("MEDHVAL", "PCTBACHMOR", "NBELPOV100", "PCTVACANT", "PCTSINGLES"),
names_to = "Variable",
values_to = "Value")
ggplot(longer_version,aes(x = Value)) +
geom_histogram(aes(y = ..count..), fill = "black", alpha = 0.7) +
facet_wrap(~Variable, scales = "free", ncol = 3, labeller = as_labeller(c(
"MEDHVAL" = "Median House Value",
"PCTBACHMOR" = "% with Bachelor’s Degrees or Higher",
"NBELPOV100" = "# Households Living in Poverty",
"PCTVACANT" = "% of Vacant Houses",
"PCTSINGLES" = "% of Single House Units"
))) +
labs(x = "Value", y = "Count", title = "Histograms of Dependent and Predictor Variables") +
theme_light() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8))

# histograms of the transformed variables
longer_version2 <- data %>%
pivot_longer(cols = c(LNMEDHVAL, LNPCTBACHMOR ,LNNBELPOV100,LNPCTVACANT, LNPCTSINGLES),
names_to = "Variable",
values_to = "Value")
ggplot(longer_version2,aes(x = Value)) +
geom_histogram(aes(y = ..count..), fill = "red", alpha = 0.7) +
facet_wrap(~Variable, scales = "free", ncol = 3, labeller = as_labeller(c(
"LNMEDHVAL" = "Log Median House Value",
"LNPCTBACHMOR" = "Log % with Bachelor’s Degree",
"LNNBELPOV100" = "Log # Households in Poverty",
"LNPCTVACANT" = "Log % Vacant Houses",
"LNPCTSINGLES" = "Log % Single House Units"
))) +
labs(x = "Value", y = "Count", title = "Histograms of Dependent and log transformed Predictor Variables") +
theme_light() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8))

ggplot(shape) +
geom_sf(aes(fill = LNMEDHVAL), color = "transparent") +
scale_fill_gradientn(colors = c("#fff0f3", "#a4133c"),
name = "LNMEDHVAL",
na.value = "transparent") +
theme(legend.text = element_text(size = 9),
legend.title = element_text(size = 10),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
panel.background = element_blank(),
panel.border = element_rect(colour = "grey", fill = NA, size = 0.8)) +
labs(title = "Log Transformed Median House Value")

shpe_longer<- shape %>%
pivot_longer(cols = c("PCTVACANT", "PCTSINGLES", "PCTBACHMOR", "LNNBELPOV"),
names_to = "Variable",
values_to = "Value")
custom_titles <- c(
PCTVACANT = "Percent of Vacant Houses",
PCTSINGLES = "Percent of Single House Units",
PCTBACHMOR = "Percent of Bachelor's Degree or Higher",
LNNBELPOV = "Logged Transformed Poverty Rate"
)
plot_list <- lapply(unique(shpe_longer$Variable), function(var_name) {
data_subset <- subset(shpe_longer, Variable == var_name)
ggplot(data_subset) +
geom_sf(aes(fill = Value), color = "transparent") +
scale_fill_gradientn(
colors = c("#fff0f3", "#a4133c"),
name = var_name,
na.value = "transparent"
) +
labs(title = custom_titles[[var_name]]) +
theme(
legend.text = element_text(size = 8),
legend.title = element_text(size = 10),
legend.key.size = unit(0.3, "cm"),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 15, face = "bold"),
panel.background = element_blank(),
panel.border = element_rect(colour = "grey", fill = NA, size = 0.8)
)
})
# Combine the plots into a grid (2 columns by 2 rows)
combined_plot <- (plot_list[[1]] + plot_list[[2]]) /
(plot_list[[3]] + plot_list[[4]])
combined_plot

fit <- lm(LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100, data=data)
summary(fit)
##
## Call:
## lm(formula = LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR +
## LNNBELPOV100, data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.25825 -0.20391 0.03822 0.21744 2.24347
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 11.1137661 0.0465330 238.836 < 2e-16 ***
## PCTVACANT -0.0191569 0.0009779 -19.590 < 2e-16 ***
## PCTSINGLES 0.0029769 0.0007032 4.234 2.42e-05 ***
## PCTBACHMOR 0.0209098 0.0005432 38.494 < 2e-16 ***
## LNNBELPOV100 -0.0789054 0.0084569 -9.330 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.3665 on 1715 degrees of freedom
## Multiple R-squared: 0.6623, Adjusted R-squared: 0.6615
## F-statistic: 840.9 on 4 and 1715 DF, p-value: < 2.2e-16
anova_table <- anova(fit)
anova_table
## Analysis of Variance Table
##
## Response: LNMEDHVAL
## Df Sum Sq Mean Sq F value Pr(>F)
## PCTVACANT 1 180.392 180.392 1343.087 < 2.2e-16 ***
## PCTSINGLES 1 24.543 24.543 182.734 < 2.2e-16 ***
## PCTBACHMOR 1 235.118 235.118 1750.551 < 2.2e-16 ***
## LNNBELPOV100 1 11.692 11.692 87.054 < 2.2e-16 ***
## Residuals 1715 230.344 0.134
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
fitted_values <- fitted(fit)
residuals_values <- residuals(fit)
standardized_residuals <- rstandard(fit)
data <- data %>%
mutate(
Fitted = fitted_values,
Residuals = residuals_values,
Standardized_Residuals = standardized_residuals)
ggplot(data, aes(x = Fitted, y = Standardized_Residuals)) +
geom_point(color = "black") +
geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
labs(
title = "Scatter Plot of Standardized Residuals vs Fitted Values",
x = "Predicted Values",
y = "Standardized Residuals"
) +
theme_minimal() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8))

ggplot(data, aes(x = Standardized_Residuals)) +
geom_histogram(bins = 30, fill = "black") +
labs(title = "Histogram of Standardized Residuals",
x = "Standardized Residuals",
y = "Frequency") +
theme_minimal() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8))

longer<-data %>%
pivot_longer(cols = c("PCTBACHMOR", "LNNBELPOV100", "PCTVACANT", "PCTSINGLES"),
names_to = "Variable",
values_to = "Value")
ggplot(longer,aes(x = Value, y = LNMEDHVAL)) +
geom_point(color = "black") +
geom_smooth(method = "lm", color = "red", se = FALSE) +
facet_wrap(~ Variable, scales = "free", labeller = as_labeller(c(
"PCTBACHMOR" = "% with Bachelor’s Degrees or Higher",
"LNNBELPOV100" = "Logged Households Living in Poverty",
"PCTVACANT" = "% of Vacant Houses",
"PCTSINGLES" = "% of Single House Units"
))) +
theme_light() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8)) +
labs(title = "Scatter Plots of Dependent Variable vs. Predictors",
x = "Predictor Value",
y = "Log of Median House Value")

custom_labels <- c(
"% of Individuals with Bachelor’s Degrees or Higher" = "PCTBACHMOR",
"% of Vacant Houses" = "PCTVACANT",
"% of Single House Units" = "PCTSINGLES",
"# Households Living in Poverty" = "LNNBELPOV100"
)
predictor_vars <- data[, c("PCTVACANT", "PCTSINGLES", "PCTBACHMOR", "LNNBELPOV100")]
cor_matrix <- cor(predictor_vars, use = "complete.obs", method = "pearson")
rownames(cor_matrix) <- names(custom_labels)
colnames(cor_matrix) <- names(custom_labels)
ggcorrplot(cor_matrix,
method = "square",
type = "lower",
lab = TRUE,
lab_size = 3,
colors = c("#d73027", "white", "#1a9850"))+
labs(title = "Correlation Matrix for all Predictor Variables") +
theme(plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x = element_text(size = 7),
axis.text.y = element_text(size = 7),
axis.title = element_text(size = 8))

LS0tCnRpdGxlOiAnVXNpbmcgT0xTIFJlZ3Jlc3Npb24gdG8gUHJlZGljdCBNZWRpYW4gSG91c2UgVmFsdWVzIGluIFBoaWxhZGVscGhpYScKYXV0aG9yOiAiWmhhbmNoYW8gWWFuZywgSGFveXUgWmh1LCBLYXZhbmEgUmFqdSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogdW5pdGVkCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQoKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoc2YpCmxpYnJhcnkodGlkeWNlbnN1cykKbGlicmFyeShrbml0cikgCmxpYnJhcnkoZ3QpIApsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoZ2djb3JycGxvdCkKbGlicmFyeShwYXRjaHdvcmspCmBgYAoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGluY2x1ZGU9IEZBTFNFfQojIExvYWQgdGhlIGRhdGEKZGF0YSA8LSByZWFkLmNzdigiZGF0YS9SZWdyZXNzaW9uRGF0YS5jc3YiKQpzaGFwZSA8LSBzdF9yZWFkKCJkYXRhL1JlZ3Jlc3Npb25EYXRhLnNocCIpCmBgYAoKCmBgYHtyIHN1bW1hcnkgc3RhdHMsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmRlcGVuZGVudF92YXIgPC0gIk1FREhWQUwiCgpwcmVkaWN0b3JzIDwtIGMoIlBDVEJBQ0hNT1IiLCAiTkJFTFBPVjEwMCIsICJQQ1RWQUNBTlQiLCAiUENUU0lOR0xFUyIpCgpzdW1tYXJ5X3N0YXRzIDwtIGRhdGEgJT4lCiAgc2VsZWN0KGFsbF9vZihjKGRlcGVuZGVudF92YXIsIHByZWRpY3RvcnMpKSkgJT4lCiAgc3VtbWFyaXNlX2FsbChsaXN0KE1lYW4gPSBtZWFuLCBTRCA9IHNkKSwgbmEucm0gPSBUUlVFKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGV2ZXJ5dGhpbmcoKSwgbmFtZXNfdG8gPSAiVmFyaWFibGUiLCB2YWx1ZXNfdG8gPSAiVmFsdWUiKSAlPiUKICBzZXBhcmF0ZShWYXJpYWJsZSwgaW50byA9IGMoIlZhcmlhYmxlIiwgIlN0YXQiKSwgc2VwID0gIl8iKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gU3RhdCwgdmFsdWVzX2Zyb20gPSBWYWx1ZSkKCgoKc3VtbWFyeV9zdGF0cyRWYXJpYWJsZSA8LSByZWNvZGUoc3VtbWFyeV9zdGF0cyRWYXJpYWJsZSwKICAiTUVESFZBTCIgPSAiTWVkaWFuIEhvdXNlIFZhbHVlIiwKICAiTkJFTFBPVjEwMCIgPSAiIyBIb3VzZWhvbGRzIExpdmluZyBpbiBQb3ZlcnR5IiwKICAiUENUQkFDSE1PUiIgPSAiJSBvZiBJbmRpdmlkdWFscyB3aXRoIEJhY2hlbG9y4oCZcyBEZWdyZWVzIG9yIEhpZ2hlciIsCiAgIlBDVFZBQ0FOVCIgPSAiJSBvZiBWYWNhbnQgSG91c2VzIiwKICAiUENUU0lOR0xFUyIgPSAiJSBvZiBTaW5nbGUgSG91c2UgVW5pdHMiCikKCgoKc3VtbWFyeV9zdGF0cyA8LSBzdW1tYXJ5X3N0YXRzICU+JQogIG11dGF0ZSgKICAgIE1lYW4gPSByb3VuZChNZWFuLCAyKSwKICAgIFNEID0gcm91bmQoU0QsIDIpCiAgKQoKc3VtbWFyeV9zdGF0cyA8LSBzdW1tYXJ5X3N0YXRzICU+JQogIGFycmFuZ2UoVmFyaWFibGUgPT0gIk1lZGlhbiBIb3VzZSBWYWx1ZSIpCgpwcmVkaWN0b3Jfcm93cyA8LSB3aGljaChzdW1tYXJ5X3N0YXRzJFZhcmlhYmxlICE9ICJNZWRpYW4gSG91c2UgVmFsdWUiKQpkZXBlbmRlbnRfcm93cyA8LSB3aGljaChzdW1tYXJ5X3N0YXRzJFZhcmlhYmxlID09ICJNZWRpYW4gSG91c2UgVmFsdWUiKQoKIyBEZXRlcm1pbmUgdGhlIHN0YXJ0IGFuZCBlbmQgcm93cyBmb3IgZWFjaCBncm91cApzdGFydF9wcmVkIDwtIG1pbihwcmVkaWN0b3Jfcm93cykKZW5kX3ByZWQgICA8LSBtYXgocHJlZGljdG9yX3Jvd3MpCnN0YXJ0X2RlcCAgPC0gbWluKGRlcGVuZGVudF9yb3dzKQplbmRfZGVwICAgIDwtIG1heChkZXBlbmRlbnRfcm93cykKCiMgQ3JlYXRlIHRoZSB0YWJsZSB1c2luZyBrYWJsZSBhbmQgYWRkIGV4dHJhIGZvcm1hdHRpbmcKa2FibGUoc3VtbWFyeV9zdGF0cywgY2FwdGlvbiA9ICJTdW1tYXJ5IFN0YXRpc3RpY3MiLCAKICAgICAgYWxpZ24gPSBjKCJsIiwgImwiLCAibCIpLCBib29rdGFicyA9IFRSVUUsIGVzY2FwZSA9IEZBTFNFICkgJT4lCiAgYWRkX2hlYWRlcl9hYm92ZShjKCIgIiA9IDEsICJTdGF0aXN0aWNzIiA9IDIpKSAlPiUKICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSkgJT4lCiAgZ3JvdXBfcm93cygiUHJlZGljdG9ycyIsIHN0YXJ0X3ByZWQsIGVuZF9wcmVkKSAlPiUKICBncm91cF9yb3dzKCJEZXBlbmRlbnQgVmFyaWFibGUiLCBzdGFydF9kZXAsIGVuZF9kZXApJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBUUlVFKQoKYGBgCgoKCmBgYHtyfQojY2hlY2sgMApjb2x1bW5zX3RvX2NoZWNrIDwtIGMoZGVwZW5kZW50X3ZhciwgcHJlZGljdG9ycykKCnplcm9fY291bnRzIDwtIHNhcHBseShkYXRhW2NvbHVtbnNfdG9fY2hlY2tdLCBmdW5jdGlvbih4KSBzdW0oeCA9PSAwLCBuYS5ybSA9IFRSVUUpKQoKemVyb19jb3VudHNbemVyb19jb3VudHMgPiAwXQoKYGBgCgpgYGB7cn0KZGF0YSA8LSBkYXRhICU+JQogIG11dGF0ZSgKICAgIExOTUVESFZBTCA9IGxvZyhNRURIVkFMKSwKICAgIExOUENUQkFDSE1PUiA9IGxvZygxK1BDVEJBQ0hNT1IpLAogICAgTE5OQkVMUE9WMTAwID0gbG9nKDErTkJFTFBPVjEwMCksCiAgICBMTlBDVFZBQ0FOVCA9IGxvZygxK1BDVFZBQ0FOVCksCiAgICBMTlBDVFNJTkdMRVMgPSBsb2coMStQQ1RTSU5HTEVTKQogICkKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9OSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbG9uZ2VyX3ZlcnNpb248LSBkYXRhICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYygiTUVESFZBTCIsICJQQ1RCQUNITU9SIiwgIk5CRUxQT1YxMDAiLCAiUENUVkFDQU5UIiwgIlBDVFNJTkdMRVMiKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiVmFyaWFibGUiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiVmFsdWUiKQoKZ2dwbG90KGxvbmdlcl92ZXJzaW9uLGFlcyh4ID0gVmFsdWUpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmNvdW50Li4pLCBmaWxsID0gImJsYWNrIiwgYWxwaGEgPSAwLjcpICsgIAogIGZhY2V0X3dyYXAoflZhcmlhYmxlLCBzY2FsZXMgPSAiZnJlZSIsIG5jb2wgPSAzLCBsYWJlbGxlciA9IGFzX2xhYmVsbGVyKGMoCiAgICAiTUVESFZBTCIgPSAiTWVkaWFuIEhvdXNlIFZhbHVlIiwKICAgICJQQ1RCQUNITU9SIiA9ICIlIHdpdGggQmFjaGVsb3LigJlzIERlZ3JlZXMgb3IgSGlnaGVyIiwKICAgICJOQkVMUE9WMTAwIiA9ICIjIEhvdXNlaG9sZHMgTGl2aW5nIGluIFBvdmVydHkiLAogICAgIlBDVFZBQ0FOVCIgPSAiJSBvZiBWYWNhbnQgSG91c2VzIiwKICAgICJQQ1RTSU5HTEVTIiA9ICIlIG9mIFNpbmdsZSBIb3VzZSBVbml0cyIKICApKSkgKyAgCiAgbGFicyh4ID0gIlZhbHVlIiwgeSA9ICJDb3VudCIsIHRpdGxlID0gIkhpc3RvZ3JhbXMgb2YgRGVwZW5kZW50IGFuZCBQcmVkaWN0b3IgVmFyaWFibGVzIikgKwogIHRoZW1lX2xpZ2h0KCkgKyAgIAogIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksIAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTYpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTYpLCAKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTgpKQpgYGAKCgpgYGB7ciwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9OSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBoaXN0b2dyYW1zIG9mIHRoZSB0cmFuc2Zvcm1lZCB2YXJpYWJsZXMKbG9uZ2VyX3ZlcnNpb24yIDwtIGRhdGEgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKExOTUVESFZBTCwgTE5QQ1RCQUNITU9SICxMTk5CRUxQT1YxMDAsTE5QQ1RWQUNBTlQsIExOUENUU0lOR0xFUyksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlZhcmlhYmxlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlZhbHVlIikKCmdncGxvdChsb25nZXJfdmVyc2lvbjIsYWVzKHggPSBWYWx1ZSkpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uY291bnQuLiksIGZpbGwgPSAicmVkIiwgYWxwaGEgPSAwLjcpICsgIAogIGZhY2V0X3dyYXAoflZhcmlhYmxlLCBzY2FsZXMgPSAiZnJlZSIsIG5jb2wgPSAzLCBsYWJlbGxlciA9IGFzX2xhYmVsbGVyKGMoCiAgICAiTE5NRURIVkFMIiA9ICJMb2cgTWVkaWFuIEhvdXNlIFZhbHVlIiwKICAgICJMTlBDVEJBQ0hNT1IiID0gIkxvZyAlIHdpdGggQmFjaGVsb3LigJlzIERlZ3JlZSIsCiAgICAiTE5OQkVMUE9WMTAwIiA9ICJMb2cgIyBIb3VzZWhvbGRzIGluIFBvdmVydHkiLAogICAgIkxOUENUVkFDQU5UIiA9ICJMb2cgJSBWYWNhbnQgSG91c2VzIiwKICAgICJMTlBDVFNJTkdMRVMiID0gIkxvZyAlIFNpbmdsZSBIb3VzZSBVbml0cyIKICApKSkgKyAgCiAgbGFicyh4ID0gIlZhbHVlIiwgeSA9ICJDb3VudCIsIHRpdGxlID0gIkhpc3RvZ3JhbXMgb2YgRGVwZW5kZW50IGFuZCBsb2cgdHJhbnNmb3JtZWQgUHJlZGljdG9yIFZhcmlhYmxlcyIpICsKICB0aGVtZV9saWdodCgpICsgICAKICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT02KSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT02KSwgCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT04KSkKYGBgCgoKCgpgYGB7cixmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD05LHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmdncGxvdChzaGFwZSkgKwogIGdlb21fc2YoYWVzKGZpbGwgPSBMTk1FREhWQUwpLCBjb2xvciA9ICJ0cmFuc3BhcmVudCIpICsKICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvcnMgPSBjKCIjZmZmMGYzIiwgIiNhNDEzM2MiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJMTk1FREhWQUwiLCAKICAgICAgICAgICAgICAgICAgICAgICBuYS52YWx1ZSA9ICJ0cmFuc3BhcmVudCIpICsgCiAgdGhlbWUobGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSwgZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImdyZXkiLCBmaWxsID0gTkEsIHNpemUgPSAwLjgpKSArCiAgbGFicyh0aXRsZSA9ICJMb2cgVHJhbnNmb3JtZWQgTWVkaWFuIEhvdXNlIFZhbHVlIikKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xNSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0Kc2hwZV9sb25nZXI8LSBzaGFwZSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoIlBDVFZBQ0FOVCIsICJQQ1RTSU5HTEVTIiwgIlBDVEJBQ0hNT1IiLCAiTE5OQkVMUE9WIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlZhcmlhYmxlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlZhbHVlIikKY3VzdG9tX3RpdGxlcyA8LSBjKAogIFBDVFZBQ0FOVCAgID0gIlBlcmNlbnQgb2YgVmFjYW50IEhvdXNlcyIsCiAgUENUU0lOR0xFUyAgPSAiUGVyY2VudCBvZiBTaW5nbGUgSG91c2UgVW5pdHMiLAogIFBDVEJBQ0hNT1IgID0gIlBlcmNlbnQgb2YgQmFjaGVsb3IncyBEZWdyZWUgb3IgSGlnaGVyIiwKICBMTk5CRUxQT1YgICA9ICJMb2dnZWQgVHJhbnNmb3JtZWQgUG92ZXJ0eSBSYXRlIgopCgoKCnBsb3RfbGlzdCA8LSBsYXBwbHkodW5pcXVlKHNocGVfbG9uZ2VyJFZhcmlhYmxlKSwgZnVuY3Rpb24odmFyX25hbWUpIHsKICBkYXRhX3N1YnNldCA8LSBzdWJzZXQoc2hwZV9sb25nZXIsIFZhcmlhYmxlID09IHZhcl9uYW1lKQogIAogIGdncGxvdChkYXRhX3N1YnNldCkgKwogICAgZ2VvbV9zZihhZXMoZmlsbCA9IFZhbHVlKSwgY29sb3IgPSAidHJhbnNwYXJlbnQiKSArCiAgICBzY2FsZV9maWxsX2dyYWRpZW50bigKICAgICAgY29sb3JzID0gYygiI2ZmZjBmMyIsICIjYTQxMzNjIiksCiAgICAgIG5hbWUgPSB2YXJfbmFtZSwKICAgICAgbmEudmFsdWUgPSAidHJhbnNwYXJlbnQiCiAgICApICsKICAgIGxhYnModGl0bGUgPSBjdXN0b21fdGl0bGVzW1t2YXJfbmFtZV1dKSArCiAgICB0aGVtZSgKICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjMsICJjbSIpLAogICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gIml0YWxpYyIpLAogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSwgZmFjZSA9ICJib2xkIiksCiAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiZ3JleSIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuOCkKICAgICkKfSkKCiMgQ29tYmluZSB0aGUgcGxvdHMgaW50byBhIGdyaWQgKDIgY29sdW1ucyBieSAyIHJvd3MpCmNvbWJpbmVkX3Bsb3QgPC0gKHBsb3RfbGlzdFtbMV1dICsgcGxvdF9saXN0W1syXV0pIC8KICAgICAgICAgICAgICAgICAocGxvdF9saXN0W1szXV0gKyBwbG90X2xpc3RbWzRdXSkKCmNvbWJpbmVkX3Bsb3QKYGBgCgoKYGBge3IgcmVncmVzc2lvbn0KZml0IDwtIGxtKExOTUVESFZBTCB+IFBDVFZBQ0FOVCArIFBDVFNJTkdMRVMgKyBQQ1RCQUNITU9SICsgTE5OQkVMUE9WMTAwLCBkYXRhPWRhdGEpCnN1bW1hcnkoZml0KQpgYGAKYGBge3J9CmFub3ZhX3RhYmxlIDwtIGFub3ZhKGZpdCkKYW5vdmFfdGFibGUKYGBgCmBgYHtyfQpmaXR0ZWRfdmFsdWVzIDwtIGZpdHRlZChmaXQpCnJlc2lkdWFsc192YWx1ZXMgPC0gcmVzaWR1YWxzKGZpdCkKc3RhbmRhcmRpemVkX3Jlc2lkdWFscyA8LSByc3RhbmRhcmQoZml0KQoKZGF0YSA8LSBkYXRhICU+JQogIG11dGF0ZSgKICAgIEZpdHRlZCA9IGZpdHRlZF92YWx1ZXMsCiAgICBSZXNpZHVhbHMgPSByZXNpZHVhbHNfdmFsdWVzLAogICAgU3RhbmRhcmRpemVkX1Jlc2lkdWFscyA9IHN0YW5kYXJkaXplZF9yZXNpZHVhbHMpCmBgYAoKYGBge3J9CmdncGxvdChkYXRhLCBhZXMoeCA9IEZpdHRlZCwgeSA9IFN0YW5kYXJkaXplZF9SZXNpZHVhbHMpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibGFjayIpICsgICAgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAicmVkIikgKyAgCiAgbGFicygKICAgIHRpdGxlID0gIlNjYXR0ZXIgUGxvdCBvZiBTdGFuZGFyZGl6ZWQgUmVzaWR1YWxzIHZzIEZpdHRlZCBWYWx1ZXMiLAogICAgeCA9ICJQcmVkaWN0ZWQgVmFsdWVzIiwKICAgIHkgPSAiU3RhbmRhcmRpemVkIFJlc2lkdWFscyIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKyAgIAogIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksIAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTYpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTYpLCAKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTgpKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGF0YSwgYWVzKHggPSBTdGFuZGFyZGl6ZWRfUmVzaWR1YWxzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbnMgPSAzMCwgZmlsbCA9ICJibGFjayIpICsKICBsYWJzKHRpdGxlID0gIkhpc3RvZ3JhbSBvZiBTdGFuZGFyZGl6ZWQgUmVzaWR1YWxzIiwgCiAgICAgICB4ID0gIlN0YW5kYXJkaXplZCBSZXNpZHVhbHMiLCAKICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKwogIHRoZW1lX21pbmltYWwoKSArICAgCiAgdGhlbWUocGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSxmYWNlID0gIml0YWxpYyIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9NiksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9NiksIAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OCkpCmBgYAoKCgoKCgoKCmBgYHtyIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTksIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxvbmdlcjwtZGF0YSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoIlBDVEJBQ0hNT1IiLCAiTE5OQkVMUE9WMTAwIiwgIlBDVFZBQ0FOVCIsICJQQ1RTSU5HTEVTIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlZhcmlhYmxlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlZhbHVlIikKCmdncGxvdChsb25nZXIsYWVzKHggPSBWYWx1ZSwgeSA9IExOTUVESFZBTCkpICsKICBnZW9tX3BvaW50KGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gInJlZCIsIHNlID0gRkFMU0UpICsgCiAgZmFjZXRfd3JhcCh+IFZhcmlhYmxlLCBzY2FsZXMgPSAiZnJlZSIsIGxhYmVsbGVyID0gYXNfbGFiZWxsZXIoYygKICAgICJQQ1RCQUNITU9SIiA9ICIlIHdpdGggQmFjaGVsb3LigJlzIERlZ3JlZXMgb3IgSGlnaGVyIiwKICAgICJMTk5CRUxQT1YxMDAiID0gIkxvZ2dlZCBIb3VzZWhvbGRzIExpdmluZyBpbiBQb3ZlcnR5IiwKICAgICJQQ1RWQUNBTlQiID0gIiUgb2YgVmFjYW50IEhvdXNlcyIsCiAgICAiUENUU0lOR0xFUyIgPSAiJSBvZiBTaW5nbGUgSG91c2UgVW5pdHMiCiAgKSkpICArCiAgdGhlbWVfbGlnaHQoKSArICAgCiAgdGhlbWUocGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSxmYWNlID0gIml0YWxpYyIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9NiksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9NiksIAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OCkpICsKICBsYWJzKHRpdGxlID0gIlNjYXR0ZXIgUGxvdHMgb2YgRGVwZW5kZW50IFZhcmlhYmxlIHZzLiBQcmVkaWN0b3JzIiwgCiAgICAgICB4ID0gIlByZWRpY3RvciBWYWx1ZSIsIAogICAgICAgeSA9ICJMb2cgb2YgTWVkaWFuIEhvdXNlIFZhbHVlIikKYGBgCgoKCgoKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQoKY3VzdG9tX2xhYmVscyA8LSBjKAogICIlIG9mIEluZGl2aWR1YWxzIHdpdGggQmFjaGVsb3LigJlzIERlZ3JlZXMgb3IgSGlnaGVyIiA9ICJQQ1RCQUNITU9SIiwKICAiJSBvZiBWYWNhbnQgSG91c2VzIiA9ICJQQ1RWQUNBTlQiLAogICIlIG9mIFNpbmdsZSBIb3VzZSBVbml0cyIgPSAiUENUU0lOR0xFUyIsCiAgIiMgSG91c2Vob2xkcyBMaXZpbmcgaW4gUG92ZXJ0eSIgPSAiTE5OQkVMUE9WMTAwIgopCgpwcmVkaWN0b3JfdmFycyA8LSBkYXRhWywgYygiUENUVkFDQU5UIiwgIlBDVFNJTkdMRVMiLCAiUENUQkFDSE1PUiIsICJMTk5CRUxQT1YxMDAiKV0KCmNvcl9tYXRyaXggPC0gY29yKHByZWRpY3Rvcl92YXJzLCB1c2UgPSAiY29tcGxldGUub2JzIiwgbWV0aG9kID0gInBlYXJzb24iKQpyb3duYW1lcyhjb3JfbWF0cml4KSA8LSBuYW1lcyhjdXN0b21fbGFiZWxzKQpjb2xuYW1lcyhjb3JfbWF0cml4KSA8LSBuYW1lcyhjdXN0b21fbGFiZWxzKQoKCmdnY29ycnBsb3QoY29yX21hdHJpeCwgCiAgICAgICAgICAgbWV0aG9kID0gInNxdWFyZSIsICAgCiAgICAgICAgICAgdHlwZSA9ICJsb3dlciIsICAgICAgCiAgICAgICAgICAgbGFiID0gVFJVRSwgICAgICAgCiAgICAgICAgICAgbGFiX3NpemUgPSAzLCAgICAgIAogICAgICAgICAgIGNvbG9ycyA9IGMoIiNkNzMwMjciLCAid2hpdGUiLCAiIzFhOTg1MCIpKSsKICAgIGxhYnModGl0bGUgPSAiQ29ycmVsYXRpb24gTWF0cml4IGZvciBhbGwgUHJlZGljdG9yIFZhcmlhYmxlcyIpICsKICAgIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gNyksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpLCAKICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkKYGBgCgoKCg==